package com.example.demo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.example.demo.connect.ConnectAndDisconnectActivity;

import java.lang.reflect.Method;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    // 常量
    private static final int REQ_PERMISSION_CODE = 1;
    // 实例化蓝牙控制器
    public BlueToothController btController = new BlueToothController();
    // 弹窗
    private Toast mToast;
    // 蓝牙权限列表
    public ArrayList<String> requestList = new ArrayList<>();
    // 搜索蓝牙广播
    private IntentFilter foundFilter;
    //
    public ArrayAdapter adapter1;
    //定义一个列表，存蓝牙设备的地址。
    public ArrayList<String> arrayList=new ArrayList<>();
    //定义一个列表，存蓝牙设备地址，用于显示。
    public ArrayList<String> deviceName=new ArrayList<>();
    // 蓝牙状态改变广播
    private BroadcastReceiver receiver = new BroadcastReceiver(){

        /**
         * 处理蓝牙状态变化的广播接收器
         * 该方法在接收到蓝牙状态变化广播时被调用
         *
         * @param context 接收广播时的上下文环境
         * @param intent 包含蓝牙状态变化信息的意图
         */
        @Override
        public void onReceive(Context context, Intent intent) {
            // 从意图中提取蓝牙状态，如果没有指定状态，则默认为-1
            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);

            // 根据蓝牙状态显示相应的提示信息
            switch (state){
                case BluetoothAdapter.STATE_OFF:
                    // 当蓝牙状态为关闭时
                    showToast("STATE_OFF");
                    break;
                case BluetoothAdapter.STATE_ON:
                    // 当蓝牙状态为开启时
                    showToast("STATE_ON");
                    break;
                case BluetoothAdapter.STATE_TURNING_OFF:
                    // 当蓝牙状态为正在关闭时
                    showToast("STATE_TURNING_OFF");
                    break;
                case BluetoothAdapter.STATE_TURNING_ON:
                    // 当蓝牙状态为正在开启时
                    showToast("STATE_TURNING_ON");
                    break;
                default:
                    // 当蓝牙状态为未知时，显示提示信息并注销广播接收器
                    showToast("UnKnow STATE");
                    unregisterReceiver(this);
                    break;
            }
        }

    };

    // 搜索蓝牙广播
    private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {

        @SuppressLint("MissingPermission")
        @Override
        public void onReceive(Context context, Intent intent) {
            // 获取广播的类型
            String action = intent.getAction();

            // 当发现蓝牙设备时
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                String s;
                // 获取发现的蓝牙设备
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                String name=device.getName();
                // 根据设备的配对状态生成相应的信息
                if (device.getBondState() == 12) {
                    s = "设备名：" + device.getName() + "\n" + "设备地址：" + device.getAddress() + "\n" + "配对状态：已配对" + "\n";
                }
                else if (device.getBondState() == 10){
                    s = "设备名：" + device.getName() + "\n" + "设备地址：" + device.getAddress() + "\n" + "配对状态：未配对" +"\n";
                }else{
                    s = "设备名：" + device.getName() + "\n" + "设备地址：" + device.getAddress() + "\n" + "配对状态：未知" + "\n";
                }

                // 如果设备信息不在列表和设备名不是null，则添加到列表
                if (!deviceName.contains(s) && name!=null) {
                    deviceName.add(s);//将搜索到的蓝牙名称和地址添加到列表。
                    arrayList.add(device.getAddress());//将搜索到的蓝牙地址添加到列表。
                    adapter1.notifyDataSetChanged();//更新
                }
            }
            // 当蓝牙搜索结束时
            else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
                showToast("搜索结束");
                unregisterReceiver(this);
            }
            // 当蓝牙搜索开始时
            else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
                showToast("开始搜索");
            }
        }

    };

    @SuppressLint("MissingPermission")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // 初始化活动组件
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 启用Edge-to-Edge显示
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return WindowInsetsCompat.CONSUMED;
        });

        // 蓝牙状态改变信息
        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        // 注册广播
        registerReceiver(receiver, filter);
        // 搜索蓝牙的广播
        foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        // 获取ListView组件
        ListView listView = findViewById(R.id.listview1);
        // 实例化ArrayAdapter对象
        adapter1 = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, deviceName);
        // 添加到ListView组件中
        listView.setAdapter(adapter1);

        // 处理ListView项点击事件
        listView.setOnItemClickListener((adapterView, view, i, l) -> {
            try {
                // 获取点击项的文本内容
                CharSequence content = ((TextView) view).getText();
                String con = content.toString();
                //解析内容（根据换行符将其分为三个元素，["设备名：xxx", "设备地址：xx：xx：xx：xx", "配对状态：xxx"]）
                // 解析设备地址
                String[] conArray = con.split("\n");
                if (conArray.length < 2) {
                    showToast("无效的设备信息");
                    return;
                }

                //蓝牙名称
                String bluetooth_name = conArray[0].substring(4);
                //蓝牙地址
                String bluetooth_address = conArray[1].substring(5).trim();



                // 根据地址查找蓝牙设备
                BluetoothDevice device = btController.find_device(bluetooth_address);
                if (device == null) {
                    showToast("找不到设备");
                    return;
                }

                // 检查设备配对状态并进行相应操作
                handleDeviceBonding(device,bluetooth_name,bluetooth_address);


            } catch (Exception e) {
                showToast("发生错误: " + e.getMessage());
                Log.e("BluetoothError", "Error handling device bonding", e);
            }
        });





        // 通过id获取”搜索可见蓝牙“按钮
        Button button_6 = findViewById(R.id.button10);
        // 绑定按钮点击事件处理函数
        button_6.setOnClickListener(view -> {
            // 获取蓝牙权限
            getPermission();
            // 注册广播
            registerReceiver(bluetoothReceiver, foundFilter);
            // 初始化各列表
            arrayList.clear();
            deviceName.clear();
            adapter1.notifyDataSetChanged();
            // 开始搜索
            btController.findDevice();
        });

        // 通过id获取“查看已绑定蓝牙”按钮
        Button button_7 = findViewById(R.id.button11);
        // 绑定按钮点击事件处理函数
        button_7.setOnClickListener(view -> {
            // 取消当前蓝牙控制器的搜索操作，以防止搜索影响查看已绑定蓝牙操作
            btController.cancelSearch();
            // 获取蓝牙权限
            getPermission();
            // 初始化各列表
            deviceName.clear();
            arrayList.clear();

            // 异步获取已绑定蓝牙设备列表
            new Thread(() -> {
                ArrayList<BluetoothDevice> bluetoothDevices = btController.getBondedDeviceList();
                if (bluetoothDevices != null) {
                    runOnUiThread(() -> {
                        Toast.makeText(this, "找到 " + bluetoothDevices.size() + " 个已绑定设备", Toast.LENGTH_SHORT).show();
                        for (BluetoothDevice device : bluetoothDevices) {
                            String address = device.getAddress();
                            String name = device.getName();
                            if (address == null) {
                                address = "未知地址";
                            }
                            if (name == null) {
                                name = "未知名称";
                            }
                            arrayList.add(address);
                            switch (device.getBondState()) {
                                case BluetoothDevice.BOND_BONDED:
                                    deviceName.add("设备名：" + name + "\n" + "设备地址：" + address + "\n" + "配对状态：已配对" + "\n");
                                    break;
                                case BluetoothDevice.BOND_NONE:
                                    deviceName.add("设备名：" + name + "\n" + "设备地址：" + address + "\n" + "配对状态：未配对" + "\n");
                                    break;
                                default:
                                    deviceName.add("设备名：" + name + "\n" + "设备地址：" + address + "\n" + "配对状态：未知" + "\n");
                                    break;
                            }
                        }
                        adapter1.notifyDataSetChanged();
                    });
                } else {
                    runOnUiThread(() -> Toast.makeText(this, "未找到任何已绑定设备", Toast.LENGTH_SHORT).show());
                }
            }).start();

        });

    }


    /**
     * 处理蓝牙设备的配对状态
     * 当设备未配对时，尝试与设备配对；当设备已配对时，跳转到其他页面
     *
     * @param device BluetoothDevice对象，代表需要处理配对状态的蓝牙设备
     */
    @SuppressLint("MissingPermission")
    private void handleDeviceBonding(BluetoothDevice device,String bluetooth_name,String bluetooth_address) {
        btController.cancelSearch();

        if (device.getBondState() == BluetoothDevice.BOND_NONE) {
            device.createBond();
            updateDeviceList(device, "已配对");
            showToast("配对：" + device.getName());
        } else if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
            //页面带参数跳转
            Intent intent = new Intent(MainActivity.this, ConnectAndDisconnectActivity.class);
            intent.putExtra("bluetooth_name", bluetooth_name);
            intent.putExtra("bluetooth_address", bluetooth_address);
            startActivity(intent);

        }
    }


    /**
     * 获取设备信息字符串
     * 此方法用于生成一个包含蓝牙设备信息的字符串，包括设备名称、设备地址和配对状态
     *
     * @param device BluetoothDevice对象，代表一个远程蓝牙设备
     * @param bondStatus 字符串，表示设备的配对状态
     * @return 返回一个格式化后的设备信息字符串
     *
     */
    @SuppressLint("MissingPermission")
    private String getDeviceInfoString(BluetoothDevice device, String bondStatus) {
        // 使用资源文件中的格式化字符串，结合设备名称、设备地址和配对状态，生成设备信息字符串
        return getString(R.string.device_info_format, device.getName(), device.getAddress(), bondStatus);
    }


    /**
     * 更新设备列表中的设备信息
     * 此方法用于根据蓝牙设备的配对状态更新界面上显示的设备列表
     * 它通过比较设备的当前配对状态与之前的状态，来决定是否需要更新列表
     *
     * @param device 蓝牙设备对象，代表需要更新的设备
     * @param bondStatus 字符串，表示设备当前的配对状态，"已配对"或"未配对"
     */
    private void updateDeviceList(BluetoothDevice device, String bondStatus) {
        String oldDeviceInfo = getDeviceInfoString(device, bondStatus.equals("已配对") ? "未配对" : "已配对");
        String newDeviceInfo = getDeviceInfoString(device, bondStatus);

        if (deviceName.contains(oldDeviceInfo)) {
            deviceName.remove(oldDeviceInfo);
            deviceName.add(newDeviceInfo);
            runOnUiThread(() -> adapter1.notifyDataSetChanged());
        }
    }


    /**
     * Toast弹窗显示
     * @param text  显示文本
     */
    public void showToast(String text){
        // 若Toast控件未初始化
        if( mToast == null){
            // 则初始化
            mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
        }
        // 否则
        else{
            // 修改显示文本
            mToast.setText(text);
        }
        // 显示
        mToast.show();
    }


    /**
     * 尝试取消配对
     * @param device 要取消配对的蓝牙设备对象
     */
    private void unpairDevice(BluetoothDevice device) {
        try {
            // 使用反射调用BluetoothDevice对象的removeBond方法来取消配对
            Method m = device.getClass()
                    .getMethod("removeBond", (Class[]) null);
            m.invoke(device, (Object[]) null);
        } catch (Exception e) {
            // 异常处理：打印异常信息
            e.printStackTrace();
        }
    }

    /**
     * 动态申请权限
     * 此方法用于根据设备的Android版本动态申请所需的权限
     * 在Android S及以上版本，需要申请蓝牙扫描、广告、连接以及位置权限
     * 如果请求列表不为空，则通过ActivityCompat.requestPermissions方法申请权限
     */
    public void getPermission(){
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
            requestList.add(Manifest.permission.BLUETOOTH_SCAN);
            requestList.add(Manifest.permission.BLUETOOTH_ADVERTISE);
            requestList.add(Manifest.permission.BLUETOOTH_CONNECT);
            requestList.add(Manifest.permission.ACCESS_FINE_LOCATION);
            requestList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
            requestList.add(Manifest.permission.BLUETOOTH);
        }

        if(!requestList.isEmpty()){
            ActivityCompat.requestPermissions(this, requestList.toArray(new String[0]), REQ_PERMISSION_CODE);
        }
    }


    /**
     * 处理活动结果回调
     * 当启动其他活动（如拍照、选择文件等）并返回结果时，该方法被调用
     *
     * @param requestCode 请求码，表示启动活动时传递的请求类型
     * @param resultCode  结果码，表示活动返回结果的状态
     * @param data        返回的Intent数据，包含活动返回的附加信息
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        super.onActivityResult(requestCode, resultCode, data);

    }

}
